import type {AxiosInstance, AxiosRequestConfig, CustomParamsSerializer, AxiosResponse} from 'axios';
import Axios from 'axios';
import {message} from 'ant-design-vue';
import {Modal} from 'ant-design-vue';
import {useUserStore} from '@/models/user';
import {getToken} from '@/utils/auth';
import {errorCode} from '@/utils/errorCode';
// 是否显示重新登录
export const isRelogin = {show: false};
const VITE_APP_BASE_API = '/dev-api';
const defaultConfig: AxiosRequestConfig = {
  baseURL: VITE_APP_BASE_API,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
  // 请求超时时间
  timeout: 10000,
};

class InstanceRequest {
  constructor() {
    this.interceptorsRequest();
    this.interceptorsResponse();
  }
  /** 保存当前Axios实例对象 */
  private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);

  /** 请求拦截 */
  private interceptorsRequest = () => {
    InstanceRequest.axiosInstance.interceptors.request.use(
      (config: any): Promise<any> => {
        // 是否需要设置 token
        const isToken = (config.headers || {}).isToken === false;
        // 是否需要防止数据重复提交
        const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;

        if (getToken() && !isToken) {
          config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
        }
        /** 请求白名单，放置一些不需要token的接口（通过设置请求白名单，防止token过期后再请求造成的死循环问题） */
        const whiteList = ['/refreshToken', '/login'];

        return config;
      },
      (error) => {
        console.log('请求拦截报错了===》', error);
        return Promise.reject(error);
      },
    );
  };
  /** 响应拦截 */
  private interceptorsResponse = () => {
    InstanceRequest.axiosInstance.interceptors.response.use(
      (response: any): any => {
        // 未设置状态码则默认成功状态
        const code = response.data.code || 200;
        // 获取错误信息
        const msg = errorCode[code] || response.data.msg || errorCode['default'];

        // 二进制数据则直接返回
        if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
          return response.data;
        }

        if (code === 401) {
          const userModel = useUserStore();
          if (!isRelogin.show) {
            // 登陆状态已过期 请重新登陆
            isRelogin.show = true;
            userModel.logOut({msg: '登陆状态已过期 请重新登陆'});
          }
        } else if (code === 500) {
          message.error(msg);
          console.log(new Error('code：500 =》' + msg));
          return Promise.reject(code);
        } else if (code === 601) {
          message.error(msg);
          return Promise.reject(new Error(msg));
        } else if (code !== 200) {
          message.error(msg);
          return Promise.reject('error');
        } else {
          return Promise.resolve(response.data);
        }
      },
      (error: any) => {
        console.log('响应拦截 Error 报错了', error);
        let {message} = error;
        if (message == 'Network Error') {
          message = '后端接口连接异常';
        } else if (message.includes('timeout')) {
          message = '系统接口请求超时';
        } else if (message.includes('Request failed with status code')) {
          message = '系统接口' + message.substr(message.length - 3) + '异常';
        }
        // 关闭进度条动画
        // NProgress.done();
        // 所有的响应异常 区分来源为取消请求/非取消请求
        message.error(message);
        return Promise.reject(error);
      },
    );
  };
  /** 通用请求工具函数 */
  private request<T>({method, url, params, data, ...args}: AxiosRequestConfig): Promise<T> {
    const config = {method, url, params, data, ...args} as AxiosRequestConfig;
    // 单独处理自定义请求/响应回调
    return new Promise((resolve, reject) => {
      InstanceRequest.axiosInstance
        .request(config)
        .then((response: any) => {
          resolve(response);
        })
        .catch((error) => {
          reject(error);
        });
    });
  }
  /** 单独抽离的post工具函数 */
  public get<T>({url, params, data, ...args}: any) {
    const config = {method: 'GET', url, params, data, ...args} as AxiosRequestConfig;
    return this.request<T>(config);
  }
  /** 单独抽离的post工具函数 */
  public post<T>({url, params, data, ...args}: any) {
    const config = {method: 'POST', url, params, data, ...args} as AxiosRequestConfig;
    return this.request<T>(config);
  }
  /** 单独抽离的put工具函数 */
  public put<T>({url, params, data, ...args}: any) {
    const config = {method: 'PUT', url, params, data, ...args} as AxiosRequestConfig;
    return this.request<T>(config);
  }
  /** 单独抽离的put工具函数 */
  public delete<T>({url, params, data, ...args}: any) {
    const config = {method: 'DELETE', url, params, data, ...args} as AxiosRequestConfig;
    return this.request<T>(config);
  }
}

export const request = new InstanceRequest();
